/*
 * blueprint.c - main program
 */

#include "bpcommon.h"


/* global parameter, current position of device */
char myposition[LOC_NAME_LEN+1];

/** 
  * config_dump - print configuration information onto stdout
  * @struct configparam *config - a pointer to a global configuration
  * returns: 0 on success; -1 on failure
  */
static int config_dump(struct configparam *config)
{
	int i;
	printf("interface name is: %s\n", config->wifi_ifname);
	printf("operation mode is: %d\n", config->modeflag);
	printf("fuse beacon only: %d\n", config->fusebcon);
	printf("short scan only: %d\n", config->shortscan);
	printf("set beacon allowed: %d\n", config->setbcon);
	printf("inquiry duration: %d\n", config->inqdura);
	printf("thresold: %d\n", config->threshold);
	printf("map file number: %d\n", config->num_rooms);
	printf("map filenames are ");
	for (i = 0; i < config->num_rooms; i++){
		printf("sta_%d, ", config->rmarray[i]);
	}
	printf("\n");
	return 0;
}
/** 
  * config_read - read configuration information from configuration file, "bp.conf"
  * @struct configparam *config - a pointer to a global configuration
  * returns: 0 on success; -1 on failure
  */
static int config_read(struct configparam *config)
{
	FILE *fp;
	char *line, *pos;
	size_t len = 0;
	ssize_t read;
	char strtmp[20];
	int inttmp, i, ret;
	
	fp = fopen("bp.conf", "r");
	if(fp == NULL)
		printf("open failed\n");
	memset(config, 0, sizeof(struct configparam));
	while ((read = getline(&line, &len, fp)) != -1) {
		if (strncmp(line, "#", 1) == 0){
			/* ignore comment */
		}
		else if (sscanf(line, "ifname=%s", &strtmp)){
			strcpy(config->wifi_ifname, strtmp);
		}
		else if (sscanf(line, "opmode=%d", &inttmp)){
			config->modeflag = 0;
			switch(inttmp){
				case 0: 
					/* bluetooth only mode */
					config->modeflag = config->modeflag | BTMODE;
					break;
				case 1: 
					/* wifi only mode */
					config->modeflag = config->modeflag | WIFIMODE;
					break;
				case 2: 
					/* hybrid mode */
					config->modeflag = config->modeflag | WBMODE;
					break;
				case 3: 
					/* data process mode */
					config->modeflag = config->modeflag | DATAMODE;
					break;
				default: 
					printf("Unknown operation mode\n");
					fclose(fp);
					return -1;
			}
		}
		else if (sscanf(line, "fusebcon=%d", &inttmp)){
			config->fusebcon = inttmp;
		}
		else if (sscanf(line, "shortscan=%d", &inttmp)){
			config->shortscan = inttmp;
		}
		else if (sscanf(line, "setbcon=%d", &inttmp)){
			config->setbcon = inttmp;
		}
		else if (sscanf(line, "inqdura=%d", &inttmp)){
			config->inqdura = inttmp;
		}
		else if (sscanf(line, "threshold=%d", &inttmp)){
			config->threshold = inttmp;
		}
		else if ((ret = strncmp(line, "mapfiles=", 9)) == 0) {
			config->num_rooms = 0;
			pos = line + 9;
			while (*pos != '\n'){
				while (*pos == ' '){
					pos++;
				}
				i = 0;
				while ((*pos != ',')&&(*pos != '\n')){
					strtmp[i] = *pos;
					pos++;
					i++;
				}
				strtmp[i] = '\0';
				config->rmarray[config->num_rooms] = atoi(strtmp);
				config->num_rooms++;
				pos++;
			}
		}else{
			printf("Fail to parse configuration file\n");
			fclose(fp);
			return -1;
		}
	}
	fclose(fp);
	/*config_dump(config);*/
	return 0;
}

/* 
 * main()
 */
int main(int argc, char **argv)
{
	struct rssi_map *generalmap;
	struct configparam *gconfig;
	int bconcnt;
	double mindist, threshold;

	strcpy(myposition, "unknown");
	
	printf("init\n");
	/* map initialization */
	generalmap = rssimap_init();
	if (generalmap == NULL){
		rssimap_free(generalmap);
		printf("Error\n");
		return -1;
	}

	/* read config */
	gconfig = generalmap->globalconfig;
	if(config_read(gconfig)){
		rssimap_free(generalmap);
		printf("Error\n");
		return -1;
	}

	switch(gconfig->modeflag){
		case 1: 	
			printf("Operate under Wi-Fi/Bluetooth hybrid mode. Fuse beacon only: ");
			gconfig->fusebcon == 1? printf("ON\n") : printf("OFF\n");
			break;
		case 2: 
			printf("Operate under Bluetooth mode.\n");
			break;
		case 4: 
			printf("Operate under Wi-Fi mode.\n");
			break;
		case 8: 
			printf("Operate under Data process mode.\n");
			break;
		default: 
			printf("Operate under unknown mode.\n");
			break;
	}

	/* load maps except for bluetooth only mode */
	if (!(gconfig->modeflag & BTMODE))
		rssimap_load_cache(generalmap);
	
	/* scan */
	if (!(gconfig->modeflag & DATAMODE)){
		scanner_wifi(generalmap, gconfig->shortscan);
	}else {
		/* data mode, read local observation from log files */
		printf("Start data processing\n");
		char filename[10];
		char trueposition[10];
		FILE *fplog;
		int rmidx, posidx, ret, localroom;
		for (rmidx = 0; rmidx < gconfig->num_rooms; rmidx++){
			localroom = gconfig->rmarray[rmidx];
			sprintf(filename, "dist_%d", localroom);
			fplog = fopen(filename, "a");
			ret = 0;
			posidx = 1;
			while (ret != -1){
				ret = rssimap_load_local_file(generalmap, localroom, posidx);

				if (ret == 0){
					/* fuse */
					rssimap_fuse(generalmap, 0);

					/* localize */
					rssimap_localizer(generalmap, 0, fplog);
					sprintf(trueposition, "%d_%d", localroom, posidx);
					fprintf(fplog, "True position: %s\n", trueposition);
					fprintf(fplog, "Estimated position: %s\n", myposition);

					posidx++;
				}
			}
			fclose(fplog);
		}

		/* destruction */
		/*rssimap_print(generalmap, stdout);	*/
		rssimap_free(generalmap);
		printf("Exit successfully\n");

		return 0;
	}
		
	bconcnt = -1;
	if (gconfig->modeflag & 0x03){
		bconcnt = scanner_bt(generalmap, gconfig->inqdura);
	}
	printf("%d beacons received\n", bconcnt);
	
	/* fuse and localize*/
	if ((gconfig->modeflag & WBMODE)&&(gconfig->fusebcon)){
		rssimap_fuse(generalmap, 1);
		mindist = rssimap_localizer(generalmap, 1, stdout);
	} else {
		rssimap_fuse(generalmap, 0);
		mindist = rssimap_localizer(generalmap, 0, stdout);
	}

	/* prompting */
	if (bconcnt != -1){
		threshold = (double)gconfig->threshold;
		switch(bconcnt){
			case 0: 
				btbcon_prompt(generalmap);
				mindist = 1;
				break;
			case 1: 
				if (mindist > threshold)
					btbcon_prompt(generalmap);
				break;
			default: 
				if (mindist > threshold)
					btbcon_prompt(generalmap);
				break;
		}
	}
	
	/* destruction */
	rssifgpt_print(generalmap->fgpt_head, stdout);	
	printf("Current location is %s ; with minimum distance: %lf\n", myposition, mindist);
	rssimap_free(generalmap);
	printf("Exit successfully\n");

	return 0;
}

